﻿using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using FurionApiDemo.Core.ApiResult;
using FurionApiDemo.Core.Entity;
using FurionApiDemo.Core.Extension;
using FurionApiDemo.Core.Implement.Menu.Dto;
using FurionApiDemo.Core.Implement.Role.Dto;
using FurionApiDemo.Core.Manager;
using FurionApiDemo.Core.Manager.User;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace FurionApiDemo.Core.Implement
{
    /// <summary>
    /// 角色服务
    /// </summary>
    public class RoleService : IRoleService, ITransient
    {
        private readonly IRepository<SysRole> _sysRoleRep;  // 角色表仓储 
        private readonly IRepository<SysUserRole> _sysUserRoleRep;  // 用户角色表仓储 

        private readonly IUserManager _userManager;
        private readonly IRoleMenuService _sysRoleMenuService;

        private readonly ILogger<UserService> _logger;

        public RoleService(IRepository<SysRole> sysRoleRep,
                              IRepository<SysUserRole> sysUserRoleRep,
                              IUserManager userManager,
                              IRoleMenuService sysRoleMenuService,
                              ILogger<UserService> logger)
        {
            _sysRoleRep = sysRoleRep;
            _sysUserRoleRep = sysUserRoleRep;
            _userManager = userManager;
            _sysRoleMenuService = sysRoleMenuService;
            _logger = logger;
        }

        /// <summary>
        /// 获取角色列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PagedList<RoleListOutput>> GetRoleList(RolePageInput input)
        {
            var name = !string.IsNullOrEmpty(input.Name?.Trim());
            var code = !string.IsNullOrEmpty(input.Code?.Trim());
            return await _sysRoleRep.DetachedEntities
                                    .Where((name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%")),
                                           (code, u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%")))
                                    .Where(u => u.IsDeleted == false)
                                    //.OrderBy(u => u.Sort)
                                    .Select(u => new RoleListOutput
                                    {
                                        Id = u.Id,
                                        RoleName = u.Name,
                                        Code = u.Code,
                                        Sort = u.Sort,
                                        Remark = u.Remark,
                                        Status = u.Status,
                                        CreateDateTime = u.CreatedTime
                                    }).ToPagedListAsync(input.PageNo, input.PageSize);
        }

        /// <summary>
        /// 角色下拉（用于授权角色时选择）
        /// </summary>
        /// <returns></returns>
        public async Task<dynamic> GetRoleDropDown()
        {
            // 如果不是超级管理员，则查询自己拥有的角色集合
            var roles = _userManager.SuperAdmin
                        ? new List<long>()
                        : await _sysUserRoleRep.Where(u => u.UserId == _userManager.UserId).Select(u => u.RoleId).ToListAsync();

            return await _sysRoleRep.DetachedEntities
                                    .Where(roles.Count > 0, u => roles.Contains(u.Id))
                                    .Where(u => u.Status == (int)CommonStatus.ENABLE)
                                    .Select(u => new
                                    {
                                        u.Id,
                                        u.Code,
                                        u.Name
                                    }).ToListAsync();
        }

        /// <summary>
        /// 删除角色
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public async Task DeleteRole(List<long> ids)
        {
            List<SysRole> roles = await _sysRoleRep.AsQueryable().Where(t => ids.Contains(t.Id)).ToListAsync();

            roles.ForEach(async item =>
            {
                item.Status = (int)CommonStatus.DELETED;
                item.IsDeleted = true;
                await _sysRoleRep.UpdateAsync(item);

                //var sysRole = await _sysRoleRep.FirstOrDefaultAsync(u => u.Id == item.Id);
                //await sysRole.DeleteNowAsync();

                ////级联删除该角色对应的用户-角色表关联信息
                //await _sysUserRoleService.DeleteUserRoleListByRoleId(sysRole.Id); // 避免循环引用，故用下面逻辑
            });

            var userRoles = await _sysUserRoleRep.Where(u => ids.Contains(u.RoleId)).ToListAsync();
            userRoles.ForEach(u =>
            {
                u.DeleteNow();
            });

            //级联删除该角色对应的角色-菜单表关联信息
            //await _sysRoleMenuService.DeleteRoleMenuListByRoleId(sysRole.Id);
        }

        /// <summary>
        /// 获取角色
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<RoleOutput> GetRoleInfo(long id)
        {
            SysRole role = await _sysRoleRep.AsQueryable().Include(t => t.SysRoleMenus).ThenInclude(t => t.SysMenu).FirstOrDefaultAsync(t => t.Id == id);
            RoleOutput output = role.Adapt<RoleOutput>();
            output.MenuIds = new List<MenuOutput>();
            List<SysRoleMenu> list = role.SysRoleMenus.ToList();
            for (int i = 0; i < list.Count; i++)
            {
                output.MenuIds.Add(list[i].SysMenu.Adapt<MenuOutput>());
            }
            return output;
        }

        /// <summary>
        /// 授权角色菜单
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task GrantMenu(GrantRoleMenuInput input)
        {
            await _sysRoleMenuService.GrantMenu(input);
        }

        /// <summary>
        /// 保存角色
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task SaveRole(SaveRoleInput input)
        {
            SysRole role = new SysRole();
            if (input.Id.HasValue)
            {
                //更新
                role = await _sysRoleRep.AsQueryable().FirstOrDefaultAsync(t => t.Id == input.Id);
            }
            else
            {
                if (await _sysRoleRep.AnyAsync(t => t.Name == input.Name))
                {
                    throw new Exception("角色名重复");
                }
            }
            role.Name = input.Name;
            role.Remark = input.Remark;
            role.Sort = input.Sort;
            role.Status = (int)input.Status;
            role.Code = input.Code;
            if (input.Id.HasValue)
            {
                //更新
                await _sysRoleRep.UpdateAsync(role);
            }
            else
            {
                //新增
                var backUser = await _sysRoleRep.InsertNowAsync(role);
            }
        }
    }
}
